package sw6.admin;

import java.io.IOException;

import sw6.admin.database.DatabaseHelper;
import sw6.admin.parser.ResetSettings;
import sw6.admin.parser.StoreSettings;
import sw6.admin.parser.SettingsParser;
import sw6.admin.parser.UpgradeSettings;
import sw6.lib.internal.PrivateDefinitions;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.util.Log;

public class PackageHandler extends BroadcastReceiver {
	
	private static final String LOG_NAME = "sw6.admin.PackageHandler";

	@Override
	public void onReceive(Context context, Intent intent) {
		String packageName = intent.getData().getSchemeSpecificPart();

		// We are only interested in packages beginning with sw6.* and when the database for sw6.admin has beed created
		if (packageName.startsWith(PrivateDefinitions.GIRAF_APP_PREFIX) && DatabaseHelper.checkDataBaseExsists(context)) {
			// A package is added
			if (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)) {
				Log.i(LOG_NAME, "Received Intent.ACTION_PACKAGE_ADDED");
				
				/**
				 *  Checking if the new package gonna replace another package.
				 *  If this is true we should not do anything here because we
				 *  know that Android will call our PackageHandler again with
				 *  the ACTION_PACKAGE_REPLACED intent.
				 */
				boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
				if (!replacing) {
					try {
						/**
						 * Parsing settings.xml for packageName (if exists). Every setting in the file is placed
						 * into the database.
						 */
						SettingsParser.parseAndStoreSettings(context, packageName, new StoreSettings());
						
					} catch (NameNotFoundException e) {
						/**
						 * Is not always a bug but we expect all applications packages 
						 * that begin with "sw6." has a settings.xml file.
						 */
						Log.e(LOG_NAME, "Could not find settings.xml for package: " + packageName);
						e.printStackTrace();
					} catch (IOException e) {
						Log.e(LOG_NAME, "Some IOException for package: " + packageName);
						e.printStackTrace();
					}
				} else {
					/**
					 * Because of the way Android upgrade packages we will receive 3 broadcasts:
					 * 
					 * 	- Uninstalling the package
					 * 	- Installing the package
					 * 	- Upgrading the package
					 * 
					 * For the first 2 broadcasts Android sends a boolean with whether 
					 * it is an upgrade that is performed. If this boolean is true we 
					 * know the upgradring broadcast is gonna be called later and we 
					 * will just ignore this broadcast.
					 */
					Log.i(LOG_NAME, packageName + " has replacing bit set to true. Coming back later.");
				}
			}
			
			// A package is replaced (because of upgrade)
			else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)) {
				Log.i(LOG_NAME, "Received Intent.ACTION_PACKAGE_REPLACED");
				/**
				 * TODO:
				 * Her kommer vi til at lave en hel del. Jeg vil tro at vi skal gøre følgende:
				 * 
				 * 1. Få fat i XML filen.
				 * 2. Tjek XML filen op imod databasen og slet alle variabler der kun står i databasen.
				 * 3. Tjek XML filen op imod databasen og tilføj alle variabler der kun står i XML-filen.
				 * 4. Kør initializationActivity (defineret i XML-filen) hvor der bliver sendt med at vi
				 *    vi foretager en upgrade i øjeblikket.
				 *    
				 * Det lader dog til at kunne gøres mere enkelt efter vi nu bruger parseAndStoreSettings
				 * på en smartere måde. Jeg vil tro vi kan nøjes med at lave en ny strategy til den.
				 */
				
				try {
					SettingsParser.parseAndStoreSettings(context, packageName, new UpgradeSettings());
				} catch (NameNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			// A package is removed
			else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
				Log.i(LOG_NAME, "Received Intent.ACTION_PACKAGE_REMOVED");
				boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);

				if (!replacing) {
					/**
					 * We delete all variables belonging to the package. 
					 * We are sure this is not a upgrade.
					 */
					Log.i(LOG_NAME, "Delete settings for: " + packageName);
					new DatabaseHelper(context).deleteApp(packageName);
					
				} else {
					/**
					 * See the comment about this in the code for Intent.ACTION_PACKAGE_ADDED
					 */
					Log.i(LOG_NAME, packageName + " has replacing bit set to true. Coming back later.");
				}
			} 
			
			// Data for a package is cleared
			else if (intent.getAction().equals(Intent.ACTION_PACKAGE_DATA_CLEARED)) {
				Log.i(LOG_NAME, "Received Intent.ACTION_PACKAGE_DATA_CLEARED");
				try {
					/**
					 * The user has chosen to reset all data. We must therefore 
					 * ensure that it also happens in the database.
					 * 
					 * To reset the settings we parse settings.xml for the package 
					 * and reinsert all the default settings described in settings.xml
					 */
					SettingsParser.parseAndStoreSettings(context, packageName, new ResetSettings());
					
				} catch (NameNotFoundException e) {
					/**
					 * Is not always a bug but we expect all applications packages 
					 * that begin with "sw6." has a settings.xml file.
					 */
					Log.e(LOG_NAME, "Could not find assets for package: " + packageName);
					e.printStackTrace();
				} catch (IOException e) {
					Log.e(LOG_NAME, "Some IOException for package: " + packageName);
					e.printStackTrace();
				}
			} 
			
			// This should never happen so if this information is going to the log please tell us
			else {
				Log.d(LOG_NAME, "Can't recognize this action: " + intent.getAction());
			}
		}
	}
}
